import {
  require_react
} from "./chunk-YJYY6GXC.js";
import {
  __toESM
} from "./chunk-G3PMV62Z.js";

// node_modules/@robojs/sync/.robo/build/core/utils.js
function normalizeKey(key) {
  return Array.isArray(key) ? key.join(".") : key;
}

// node_modules/@robojs/sync/.robo/build/core/context.js
var import_react = __toESM(require_react(), 1);
var SyncContext = (0, import_react.createContext)({
  cache: {},
  connected: false,
  registerCallback: () => "",
  unregisterCallback: () => {
  },
  ws: null
});
function SyncContextProvider(props) {
  const { children, loadingScreen = null } = props;
  const context = setupSyncState();
  if (loadingScreen && (!context.connected || !context.ws)) {
    return import_react.default.createElement(import_react.default.Fragment, null, loadingScreen);
  }
  return import_react.default.createElement(SyncContext.Provider, {
    value: context
  }, children);
}
var IdCounter = 0;
function setupSyncState() {
  const [ws, setWs] = (0, import_react.useState)(null);
  const [connected, setConnected] = (0, import_react.useState)(false);
  const cache = (0, import_react.useRef)({}).current;
  const callbacks = (0, import_react.useRef)({}).current;
  const callbackMap = (0, import_react.useRef)({}).current;
  const isRunning = (0, import_react.useRef)(false);
  (0, import_react.useEffect)(() => {
    if (isRunning.current) {
      return;
    }
    isRunning.current = true;
    const wsProtocol = location.protocol === "http:" ? "ws" : "wss";
    const websocket = new WebSocket(`${wsProtocol}://${location.host}/sync`);
    websocket.onopen = () => {
      console.log("Connection established at", (/* @__PURE__ */ new Date()).toISOString());
      setConnected(true);
    };
    websocket.onclose = () => {
      console.log("Connection closed at", (/* @__PURE__ */ new Date()).toISOString());
      setConnected(false);
    };
    websocket.onerror = (error) => {
      console.error("Websocket error:", error);
    };
    websocket.onmessage = (event) => {
      if (typeof event.data !== "string") {
        return;
      }
      const payload = JSON.parse(event.data);
      let response = null;
      switch (payload.type) {
        case "ping":
          response = {
            data: void 0,
            type: "pong"
          };
          break;
        case "update": {
          const { key, data } = payload;
          const cleanKey = normalizeKey(key);
          if (data === void 0) {
            break;
          }
          if (callbacks[cleanKey]) {
            callbacks[cleanKey].forEach((callback) => {
              try {
                callback(data, key);
              } catch (error) {
                console.error("Callback error:", error);
              }
            });
          }
          cache[cleanKey] = data;
          break;
        }
      }
      if (response) {
        websocket.send(JSON.stringify(response));
      }
    };
    setWs(websocket);
  }, []);
  const registerCallback = (key, callback) => {
    const cleanKey = normalizeKey(key);
    const callbackId = "" + IdCounter++;
    if (!callbacks[cleanKey]) {
      callbacks[cleanKey] = [];
    }
    callbacks[cleanKey].push(callback);
    callbackMap[callbackId] = {
      key: cleanKey,
      callback
    };
    if (callbacks[cleanKey].length === 1) {
      ws == null ? void 0 : ws.send(JSON.stringify({
        key,
        type: "on"
      }));
    } else {
      callback(cache[cleanKey], key);
    }
    return callbackId;
  };
  const unregisterCallback = (callbackId) => {
    const cleanKey = callbackMap[callbackId];
    const index = callbacks[cleanKey.key].findIndex((cb) => cb === cleanKey.callback);
    if (index > -1) {
      callbacks[cleanKey.key].splice(index, 1);
    }
    delete callbackMap[callbackId];
    if (callbacks[cleanKey.key].length === 0) {
      ws == null ? void 0 : ws.send(JSON.stringify({
        key: cleanKey.key.split("."),
        type: "off"
      }));
    }
  };
  return {
    cache,
    connected,
    registerCallback,
    unregisterCallback,
    ws
  };
}

// node_modules/@robojs/sync/.robo/build/core/useSyncState.js
var import_react2 = __toESM(require_react(), 1);
function useSyncState(initialState, key) {
  const { cache, connected, registerCallback, unregisterCallback, ws } = (0, import_react2.useContext)(SyncContext);
  const [state, setState] = (0, import_react2.useState)(initialState);
  const [queuedState, setQueuedState] = (0, import_react2.useState)(null);
  const hasWs = !!ws;
  const setSyncState = (newState) => {
    const currentState = cache[key.join(".")] ?? initialState;
    if (typeof newState === "function") {
      newState = newState(currentState);
    }
    if (connected && ws) {
      ws.send(JSON.stringify({
        data: newState,
        key,
        type: "update"
      }));
    } else {
      setQueuedState(newState);
    }
  };
  (0, import_react2.useEffect)(() => {
    if (queuedState && connected && hasWs) {
      setSyncState(queuedState);
      setQueuedState(null);
    }
    if (connected && hasWs) {
      const callbackId = registerCallback(key, (data, key2) => {
        if (key2.join(".") === key2.join(".")) {
          setState(data);
        }
      });
      return () => {
        unregisterCallback(callbackId);
      };
    }
  }, [
    connected,
    hasWs
  ]);
  return [
    state,
    setSyncState
  ];
}
export {
  SyncContextProvider,
  useSyncState
};
//# sourceMappingURL=@robojs_sync.js.map
